package listen

import (
	"fmt"
	"jgt-sdk/oper"
	"jgt-sdk/push"
	"strings"
	"time"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/internal/json"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/columnd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/util"

	"github.com/pkg/errors"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/interactiond"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd"
)

// ReplyExtral 评论推送扩展字段
type ReplyExtral struct {
	UID    string `json:"uid"`              // 评论用户
	UName  string `json:"uname"`            // 用户昵称
	Desc   string `json:"desc"`             // 评论内容
	Images string `json:"images,omitempty"` // 主体图片
	//Content     string    `json:"content"`          // 主体内容
	Title       string    `json:"title,omitempty"` // 主体标题
	Tag         string    `json:"tag,omitempty"`   // 标签
	URI         string    `json:"uri"`             // 跳转URI
	CreTime     time.Time `json:"cre_time"`        // 时间
	ReplyTarget string    // 上级评论创建人
}

// PushMeAbout 与我相关推送数据
type PushMeAbout struct {
	Header PMAHeader `json:"header"`
	Body   PMABody   `json:"body"`
	Seq    string    `json:"sequence"`
}

// PMAHeader 与我相关推送数据头部定义
type PMAHeader struct {
	Type  int         `json:"type"` //0	通用类型 1	时间扩展类型
	Title string      `json:"title"`
	Icon  string      `json:"icon"`
	Extra interface{} `json:"extra,omitempty"`
}

// PMAHeaderExtra1 头部类型1 扩展
type PMAHeaderExtra1 struct {
	Date time.Time `json:"date"`
}

// PMABody 与我相关推送数据头body定义
type PMABody struct {
	Type        int         `json:"type"`            //0	通用类型 1	时间扩展类型 2	图文标签主题扩展类型
	Description string      `json:"description"`     // 内容详情描述
	Extra       interface{} `json:"extra,omitempty"` // 扩展字段
}

// PPMABodyExtra1 BODY类型1 扩展
type PPMABodyExtra1 struct {
	Date time.Time `json:"date"`
}

// PPMABodyExtra2 BODY类型2 扩展
type PPMABodyExtra2 struct {
	Image   string `json:"image"`   // 主题相关图片地址
	Title   string `json:"title"`   // 主题相关标题
	Tag     string `json:"tag"`     // 主题相关标签
	Address string `json:"address"` // 主题相关地址路径
}

func (l listener) Reply(ctx ddd.Context, evt ddd.Event, reply *interactiond.ReplayAggregate) error {

	nrply := reply
	var rply ReplyExtral
	// 评论人
	rply.UID = reply.Creator
	if u, err := oper.GetHandle().GetUser(reply.Creator); err != nil {
		return errors.Wrapf(err, "获取用户昵称失败：%v", rply.UID)
	} else if u != nil {
		rply.UName = u.Nickname
	} else {
		return errors.Errorf("获取用户(%v)昵称失败：没有找到用户", rply.UID)
	}
	rply.CreTime = time.Now()
	uidmap := make(map[string]bool)

parent:
	if nrply.ReplayPath.ParentID != "" {
		// 存在上级回复
		pr, err := l.irar.GetReplay(ctx, nrply.ParentID)
		if err != nil {
			return errors.Wrapf(err, "获取上级回复失败")
		}
		uidmap[pr.Creator] = true
		if nrply == reply {
			// 查找上级评论人的昵称
			if u, err := oper.GetHandle().GetUser(pr.Creator); err != nil {
				return errors.Errorf("获取用户(%v)昵称失败：没有找到用户", pr.Creator)
			} else if u != nil {
				rply.ReplyTarget = u.Nickname
			} else {
				return errors.Errorf("获取用户(%v)昵称失败：没有找到用户", pr.Creator)
			}
		}
		nrply = pr
		goto parent
	}
	if rply.ReplyTarget != "" {
		rply.Desc = replyDesc2(rply.ReplyTarget, reply.Context)
		if rply.Desc == "" {
			return errors.Errorf("评论内容为空取消推送。")
		}
	}

	g, err := l.igar.GetGroup(ctx, nrply.IGID)
	if err != nil {
		return errors.Wrapf(err, "获取互动组失败")
	}
	switch g.TargetType {
	case interactiond.IGTTInfo:
		info, err := l.iar.GetInfo(ctx, g.TargetID)
		if err != nil {
			return errors.Wrapf(err, "获取互动组对应的信息(%v)失败", g.TargetID)
		}
		col, err := l.car.GetColumn(ctx, info.ColumnID)
		if err != nil {
			return errors.Wrapf(err, "获取信息所在的栏目(%v)失败:", info.ColumnID)
		}
		if len(info.Icon) > 0 {
			rply.Images = info.Icon[0]
		}
		rply.Title = util.SubStringForUnicode(info.Content, 0, 100)

		switch col.Kind {
		case columnd.ColumnKindInteractive:
			if rply.ReplyTarget == "" {
				// 查找上级评论人的昵称
				if u, err := oper.GetHandle().GetUser(info.Creator); err != nil {
					return errors.Errorf("获取用户(%v)昵称失败：没有找到用户", info.Creator)
				} else if u != nil {
					rply.Desc = replyDesc2(u.Nickname, reply.Context)
					if rply.Desc == "" {
						return errors.Errorf("评论内容为空取消推送。")
					}
				} else {
					return errors.Errorf("获取用户(%v)昵称失败：没有找到用户", info.Creator)
				}
			}
			//是互动, 则提示信息发起人
			uidmap[info.Creator] = true
			if reply.ParentID == "" {
				// 一级评论
				rply.URI = "jgt://h5app/open?URL=/interaction_detail/" + g.TargetID
			} else {
				// 二级评论
				rply.URI = "jgt://h5app/open?URL=/comment_detail/" + reply.ParentID
			}
			if len(info.Tags) > 0 {
				rply.Tag = info.Tags[0]
			} else {
				rply.Tag = "互动"
			}
		default:
			if col.Infourl != "" {
				url := strings.Replace(col.Infourl, ":infoid", info.InfoID, -1)
				rply.URI = "jgt://h5app/open?URL=" + url
			} else {
				rply.URI = "jgt://h5app/open?URL=/common_detail/" + info.InfoID
			}
			rply.Title = info.Title
			rply.Tag = col.ShortName
			if info.Owner != "" {
				uidmap[info.Owner] = true
			}
		}
	default:
	}
	uids := make([]string, 0, len(uidmap))
	for uid := range uidmap {
		if uid != rply.UID {
			uids = append(uids, uid)
		}
	}
	if len(uids) == 0 {
		return nil
	}
	extral := PushMeAbout{
		Header: PMAHeader{
			Type:  1,
			Title: rply.UName,
			Icon:  fmt.Sprintf("/api/v1/users/%s/photo", rply.UID),
			Extra: PMAHeaderExtra1{
				Date: rply.CreTime,
			},
		},
		Body: PMABody{
			Type:        2,
			Description: rply.Desc,
			Extra: PPMABodyExtra2{
				Image:   rply.Images,
				Title:   rply.Title,
				Tag:     rply.Tag,
				Address: rply.URI,
			},
		},
		Seq: rply.CreTime.Format("20060102150405"),
	}

	if err = push.GetHandle().PushToAlias("评论消息", "您有一个新的评论.", "reply", &push.ExtraItem{
		Type:      "infoReply",
		NativeURI: "jgt://message",
		Extras:    extral,
	}, uids...); err != nil {
		return errors.Wrapf(err, "推送消息失败")
	}

	return nil
}

type rplyContent struct {
	Content string   `json:"content,omitempty"`
	Img     []string `json:"img,omitempty"`
}

func replyDesc2(uname, ctt string) string {
	var rc rplyContent
	if err := json.Unmarshal([]byte(ctt), &rc); err != nil {
		return ""
	}
	format := `回复<font color="#FDCB3D">@%v</font>：%v`

	if rc.Content != "" {
		return fmt.Sprintf(format, uname, rc.Content)
	}
	if len(rc.Img) > 0 {
		return fmt.Sprintf(format, uname, "[图片]")
	}
	return ""
}
